home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Skunkware 5
/
Skunkware 5.iso
/
src
/
X11
/
wais
/
ui
/
wais-ui.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-05-09
|
24KB
|
947 lines
/*
WIDE AREA INFORMATION SERVER SOFTWARE:
No guarantees or restrictions. See the readme file for the full standard
disclaimer.
This is part of the shell user-interface tools for the WAIS software.
Do with it as you please.
jonathan@Think.COM
*
* $Log: wais-ui.c,v $
* Revision 1.22 92/05/07 14:52:04 jonathan
* Changed use of setitimer to alarm. Thanks to
* steinkel@carlisle-emh2.army.mil.
*
* Revision 1.21 92/04/30 10:59:05 jonathan
* Replace strdup with s_strdup.
*
* Revision 1.20 92/04/02 14:21:59 jonathan
* Copy type in all calls to makeDocObjUsing a generate_retrieval_apdu (which
* calls makeDocObjUsing...).
*
* Revision 1.19 92/04/01 17:19:35 jonathan
* Fixed reporting of diagnostics when return text is empty.
*
* Revision 1.18 92/03/17 14:33:17 jonathan
* Renamed to wais-ui, cleaned up for use by X interface as well as shell
* interfaces.
*
* Revision 1.17 92/03/08 10:42:28 jonathan
* Added one last loadSource in ViewWaisDocument.
*
* Revision 1.16 92/03/06 14:50:13 jonathan
* New and Improved source loading!
*
*/
#ifndef lint
static char *RCSid = "$Header: /tmp_mnt/net/quake/proj/wais/wais-8-b5/ui/RCS/wais-ui.c,v 1.22 92/05/07 14:52:04 jonathan Exp $";
#endif
#define _C_QUESTION
#include "wais.h"
#include "globals.h"
void showDiags(d)
diagnosticRecord **d;
{
int i;
char msg[256];
for (i = 0; d[i] != NULL; i++) {
if (d[i]->ADDINFO != NULL) {
sprintf(msg, "\nCode: %s, %s", d[i]->DIAG, d[i] ->ADDINFO);
PrintStatus(msg);
sleep(2);
}
}
}
void printDiags(d)
diagnosticRecord **d;
{
int i;
for (i = 0; d[i] != NULL; i++)
if (d[i]->ADDINFO != NULL)
printf("%s\n", d[i] ->ADDINFO);
}
void
write_text_record_completely(fp, record, quote_string_quotes)
FILE *fp;
WAISDocumentText *record;
Boolean quote_string_quotes;
{
long count;
/* fprintf(fp," Text\n");
print_any(" DocumentID: ", record->DocumentID);
fprintf(fp," VersionNumber: %d\n", record->VersionNumber);
*/
for(count = 0; count < record->DocumentText->size; count++){
int ch = record->DocumentText->bytes[count];
if(27 == ch){
/* then we have an escape code */
/* if the next letter is '(' or ')', then ignore two letters */
if('(' == record->DocumentText->bytes[count + 1] ||
')' == record->DocumentText->bytes[count + 1])
count += 1; /* it is a term marker */
else count += 4; /* it is a paragraph marker */
}
else if (isprint(ch)){
if(quote_string_quotes && ch == '"')
putc('\\', fp);
putc(ch, fp);
}
else if (ch == '\n' || ch == '\r')
fprintf(fp, "\n");
}
}
/* for making searches */
DocList
build_response_list(response, source)
SearchResponseAPDU *response;
SourceID source;
{
long i, k;
WAISSearchResponse *info;
DocList last = NULL, doc, result = NULL;
DocumentID docID;
k = response->NumberOfRecordsReturned;
if ( response->DatabaseDiagnosticRecords != 0 ) {
info = (WAISSearchResponse*)response->DatabaseDiagnosticRecords;
if ( info->DocHeaders != NULL ) {
for(i = 0; i < k; i++) {
if(info->DocHeaders[i] != NULL ) {
if(result == NULL) {
doc = result = makeDocList(NULL, NULL);
}
else
doc = makeDocList(NULL, NULL);
docID = fillDocumentID(info->DocHeaders[i], source);
doc->thisDoc = docID;
if(last != NULL) {
last->nextDoc = doc;
}
last = doc;
}
}
}
}
return result;
}
/* right now this hacks out the ^Q/S too. I'll do better later. */
static void
replacecontrolM(buffer, length)
char *buffer;
long *length;
{
char *here, *there, c;
long i, newlength;
here = there = buffer;
for(newlength = 0, i = 0; i < *length; i++) {
c = *here;
switch (c) {
case 0:
*there = 0;
*length = newlength;
return;
case '\r':
*there = '\n';
newlength++;
here++; there++;
break;
case 19:
case 17:
here++;
break;
default:
*there = *here;
newlength++;
here++; there++;
}
}
*length = newlength;
}
void SearchWais(q)
Question q;
{
Source source;
SList asource;
static long request_buffer_length;
DocObj **Doc;
int i;
char *request_message, *response_message;
char message[255];
DocList last;
diagnosticRecord **diag;
char *database;
long numdocs, result;
request_message = (char*)q->request_message;
response_message = (char*)q->response_message;
/* clear the results */
/*
freeDocList(q->ResultDocuments);
*/
q->ResultDocuments = NULL;
/* build DocObjs */
Doc = (DocObj**)s_malloc((q->numdocs+1) * sizeof(char*));
q->numsources = listlength((List)q->Sources);
if (q->numsources != 0)
numdocs = maxDocs/q->numsources;
else numdocs = 0;
{
DocList dl;
for(i=0, dl = q->RelevantDocuments;
dl != NULL;
dl = dl->nextDoc, i++)
if(dl->thisDoc->doc != NULL) {
char* tmptype = s_strdup((dl->thisDoc->doc->type) ?
dl->thisDoc->doc->type[0] : "TEXT");
if(dl->thisDoc->doc->id != NULL)
if(dl->thisDoc->start >= 0)
Doc[i] =
makeDocObjUsingLines(anyFromDocID(dl->thisDoc->doc->id),
tmptype, dl->thisDoc->start, dl->thisDoc->end);
else
Doc[i] =
makeDocObjUsingWholeDocument(anyFromDocID(dl->thisDoc->doc->id),
tmptype);
}
Doc[i] = NULL;
}
/* check to see if the question has a source */
source = NULL;
if(q->Sources != NULL) {
SourceList slist;
for(slist = q->Sources;
slist != NULL;
slist = slist->nextSource) {
source = findsource(slist->thisSource->filename);
if (source == NULL) {
sprintf(message, "\nCouldn't find source: %s.", slist->thisSource->filename);
PrintStatus(message);
sleep(2);
}
else {
if (strstr(source->name,".src")!=NULL) {
sprintf(message, "\nSearching: ");
strncat(message,source->name,strlen(source->name)-4);
}
else
sprintf(message, "\nSearching: %s", source->name);
PrintStatus(message);
if(source->initp != TRUE) {
PrintStatus("\nInitializing connection...");
init_for_source(source, request_message, MAX_MESSAGE_LEN,
response_message);
PrintStatus(message);
}
if(source->database[0] == 0) database = NULL;
else database = source->database;
if(source->initp != FALSE) {
result = 0;
request_buffer_length = source->buffer_length;
if(NULL ==
generate_search_apdu(request_message + HEADER_LENGTH,
&request_buffer_length,
q->keywords, database, Doc, numdocs)) {
PrintStatus("Buffer overflow: request too large");
sleep(2);
}
else if((result =
interpret_message(request_message,
(source->buffer_length -
request_buffer_length),
response_message,
source->buffer_length,
source->connection,
false /* true verbose */
)) == 0) {
PrintStatus("Warning: no information returned. Possibly a bad connection");
close_source(source);
}
if (result != 0) { /* use the repsonse */
readSearchResponseAPDU(&q->query_response,
response_message + HEADER_LENGTH);
if (q->query_response != NULL)
if ((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords != NULL)
if ((diag =
((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL)
showDiags(diag);
if (q->ResultDocuments != NULL) {
last = findLast(q->ResultDocuments);
last->nextDoc = build_response_list(q->query_response,
slist->thisSource);
}
else
q->ResultDocuments =
build_response_list(q->query_response,
slist->thisSource);
}
}
else {
sprintf(message, "\nError connecting to %s", source->name);
PrintStatus(message);
sleep(2);
}
}
}
/* ok, now we've got all the documents, let's sort them */
sort_document_list(q->ResultDocuments);
q->numresdocs = listlength((List)q->ResultDocuments);
sprintf(message, "\nFound %d items.", q->numresdocs);
PrintStatus(message);
}
else {
PrintStatus("\nThis Question has no sources to search. Please add one.");
q->ResultDocuments = NULL;
q->numresdocs = listlength((List)q->ResultDocuments);
}
if (Doc != NULL) {
doList((void**)Doc,freeDocObj);
s_free(Doc);
}
}
char* GetWaisDocument(q, doc, type, fp, written)
Question q;
DocumentID doc;
char *type;
FILE *fp;
long* written;
{
static long request_length, chars_per_page;
static long lines, size, count, chars, numChars;
long start_byte, end_byte;
any* docany;
WAISDocumentText *text;
diagnosticRecord **diag;
char *viewtext, message[255];
char *viewbuffer;
char *tmptype;
Source source;
SList asource;
char *database;
long result;
sprintf(message, "\nGetting document from server...");
if(fp != stdout)
PrintStatus(message);
source = NULL;
if(doc == NULL) return NULL;
if(doc->doc != NULL &&
doc->doc->sourceID != NULL &&
doc->doc->sourceID->filename != NULL) {
source = findsource(doc->doc->sourceID->filename);
}
if (source == NULL) {
PrintStatus("\nCould not find Source for this document!");
return NULL;
}
if(source->database[0] == 0) database = NULL;
else database = source->database;
size = 0;
lines = doc->doc->numLines;
if(written != NULL && *written != 0)
chars = *written;
else
chars = doc->doc->numChars;
numChars = chars+1000; /* for slop? */
docany = anyFromDocID(doc->doc->id);
if(source->initp == FALSE)
init_for_source(source, q->request_message, MAX_MESSAGE_LEN,
q->response_message);
if(source->initp == FALSE) {
PrintStatus("\nInit Connection Failed.");
*written = 0;
return(NULL);
}
chars_per_page = source->buffer_length - HEADER_LENGTH - 1000; /* ? */
if(fp == NULL) {
viewbuffer = (char*)s_malloc(chars < 0 ? chars_per_page : numChars);
if(viewbuffer == NULL) {
PrintStatus("\nUnable to allocate message space. Something is wrong.");
return NULL;
}
viewtext = viewbuffer;
}
tmptype = s_strdup((type ? type : "TEXT"));
if (chars == 0)
PrintStatus("\nEmpty document!");
else if (source->initp != FALSE) {
for(count = 0;
(chars < 0) || (count * chars_per_page < chars);
count++) {
/* show as we go... */
request_length = source->buffer_length;
if (chars < 0) {
numChars = (count+1) * chars_per_page;
if(fp == NULL) {
viewbuffer = s_realloc(viewbuffer, numChars);
}
}
start_byte = count * chars_per_page;
end_byte = (chars < 0 ?
(count + 1) * chars_per_page :
MIN((count + 1) * chars_per_page, chars));
if(NULL ==
generate_retrieval_apdu(q->request_message + HEADER_LENGTH,
&request_length, docany, CT_byte,
start_byte, end_byte,
tmptype, database)) {
PrintStatus("\nWarning: buffer overflow.");
return NULL;
}
if((result =
interpret_message(q->request_message,
source->buffer_length - request_length,
q->response_message,
source->buffer_length,
source->connection,
false /* true verbose */
)) == 0) {
PrintStatus("\nWarning: no information returned. Possibly a bad connection.");
close_source(source);
return NULL;
}
if (result != 0)
readSearchResponseAPDU(&q->retrieval_response,
q->response_message + HEADER_LENGTH);
if (q->retrieval_response != NULL) {
if ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords != NULL) {
diag = ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Diagnostics;
}
else diag = NULL;
if(NULL == ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text) {
if (diag != NULL)
showDiags(diag);
PrintStatus("done.");
if(written != NULL) *written = size;
return(viewbuffer);
}
else {
text = ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text[0];
if((type == NULL) || (strcmp(type, "TEXT") == 0)) {
long length = text->DocumentText->size;;
delete_seeker_codes(text->DocumentText->bytes, &length);
text->DocumentText->size = length;
replacecontrolM(text->DocumentText->bytes, &length);
text->DocumentText->size = length;
}
if(text->DocumentText->size > (end_byte - start_byte))
/* something wrong! */
text->DocumentText->size = (end_byte - start_byte);
viewtext = viewbuffer+size;
size+=text->DocumentText->size;
if (size <= numChars) {
if(fp == NULL) {
memcpy(viewtext, text->DocumentText->bytes, text->DocumentText->size);
}
else {
dumptext(fp, text->DocumentText->bytes, text->DocumentText->size);
}
sprintf(message, "\nReceived %d bytes from %s...",
size, source->server);
if(fp != stdout)
PrintStatus(message);
if(diag &&
diag[0] &&
diag[0]->ADDINFO != NULL &&
!strcmp(diag[0]->DIAG, D_PresentRequestOutOfRange))
break;
if((type != NULL) &&
(strcmp(type, "TEXT") != 0) &&
(text->DocumentText->size != chars_per_page))
break;
}
else {
PrintStatus("\nBuffer overflow!");
break;
}
}
if (diag != NULL)
showDiags(diag);
}
}
}
if (written != NULL) *written = size;
return(viewbuffer);
}
void RetrieveWaisDocument(start_output, end_output, q, doc)
void (*start_output)();
void (*end_output)();
Question q;
DocumentID doc;
{
static long request_length, chars_per_page;
static long lines, size, count, chars, numChars;
any* docany;
WAISDocumentText *text;
diagnosticRecord **diag;
char *viewtext;
char *viewbuffer;
Source source;
SList asource;
char *database;
FILE *fp;
int output_started;
output_started = FALSE;
source = NULL;
if(doc->doc != NULL) {
if(doc->doc->sourceID != NULL) {
if(doc->doc->sourceID->filename != NULL) {
char *sourcename;
sourcename = doc->doc->sourceID->filename;
for(asource = Sources;
asource != NULL;
asource = asource->nextSource) {
if (!strcmp(sourcename, asource->thisSource->name)) {
source = asource->thisSource;
break;
}
}
}
}
}
if (source == NULL) {
PrintStatus("Could not find Source for this document!");
return;
}
if(source->database[0] == 0) database = NULL;
else database = source->database;
size = 0;
lines = doc->doc->numLines;
chars = doc->doc->numChars;
numChars = chars + 1000; /* for slop? */
if((viewbuffer = (char*)s_malloc(numChars)) == NULL) {
PrintStatus("\nUnable to allocate message space. Something is wrong.");
return;
}
viewtext = viewbuffer;
docany = anyFromDocID(doc->doc->id);
if(source->initp == FALSE)
init_for_source(source, q->request_message, MAX_MESSAGE_LEN,
q->response_message);
chars_per_page = source->buffer_length - HEADER_LENGTH - 1000; /* ? */
if (chars <= 0)
PrintStatus("\nEmpty document.");
else if (source->initp != FALSE) {
for(count = 0;
count * chars_per_page < chars;
count++) {
/* show as we go... */
request_length = source->buffer_length;
if(0 ==
generate_retrieval_apdu(q->request_message + HEADER_LENGTH,
&request_length,
docany,
CT_byte,
count * chars_per_page,
MIN((count + 1) * chars_per_page, chars),
(doc->doc->type) ?
doc->doc->type[0] : "TEXT",
database)) {
PrintStatus("\nWarning: no information returned. Possibly a bad connection.");
break;
}
if(0 ==
interpret_message(q->request_message,
source->buffer_length - request_length,
q->response_message,
source->buffer_length,
source->connection,
false /* true verbose */
)) {
PrintStatus("\nWarning: no information returned. Possibly a bad connection.");
break;
}
readSearchResponseAPDU(&q->retrieval_response,
q->response_message + HEADER_LENGTH);
if (q->retrieval_response != NULL)
if ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords != NULL)
if ((diag =
((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL)
showDiags(diag);
if(NULL == ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text) {
break;
}
text = ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text[0];
{
long length;
length = text->DocumentText->size;
if((doc->doc->type == NULL) || (strcmp(doc->doc->type, "TEXT") == 0)) {
delete_seeker_codes(text->DocumentText->bytes, &length);
text->DocumentText->size = length;
replacecontrolM(text->DocumentText->bytes, &length);
text->DocumentText->size = length;
}
}
size+=text->DocumentText->size;
if (size <= numChars) {
memcpy(viewtext, text->DocumentText->bytes, text->DocumentText->size);
viewtext+=text->DocumentText->size;
}
else {
PrintStatus("\nBuffer overflow!");
break;
}
}
/* display_search_response(q->retrieval_response); the general thing */
if(NULL == ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Text){
PrintStatus("\nNo text was returned.");
} else {
if (output_started==FALSE) {
start_output(&fp);
output_started=TRUE;
if (&fp==NULL) {
PrintStatus("Unable to open output.");
return;
}
}
dumptext(fp, viewbuffer, size);
}
}
if (output_started==TRUE)
end_output(&fp);
}
void dumptext(fp, buffer, size)
FILE *fp;
char *buffer;
long size;
{
long i;
for (i = 0; i < size; i++)
fputc(*buffer++,fp);
fflush(fp);
}
#include <signal.h>
#include <setjmp.h>
static jmp_buf jbuf;
static int new, old;
static void
alarmhandler(sig, code, scp, addr)
long sig, code;
struct sigcontext *scp;
char *addr;
{
longjmp(jbuf, 1);
}
void test_connection(q)
Question q;
{
Source source;
SList asource;
static long request_buffer_length;
char *request_message, *response_message;
char message[255];
diagnosticRecord **diag;
char *database;
new = 120; /* 2 minute timeout. */
request_message = (char*)q->request_message;
response_message = (char*)q->response_message;
/* check to see if the question has a source */
source = NULL;
if(q->Sources != NULL) {
SourceList slist;
for(slist = q->Sources;
slist != NULL;
slist = slist->nextSource) {
for(asource = Sources;
asource != NULL;
asource = asource->nextSource) {
if (asource->thisSource != NULL &&
asource->thisSource->name != NULL &&
!strcmp(slist->thisSource->filename,
asource->thisSource->name)) {
source = asource->thisSource;
break;
}
}
if (source == NULL) {
sprintf(message, "\nCouldn't find source: %s.", slist->thisSource->filename);
PrintStatus(message);
}
else {
printf("Source %s ", slist->thisSource->filename);
if(source->maintainer)
printf("by %s ", source->maintainer);
if(source->server[0] != 0)
printf("at %s ", source->server);
if(source->initp == FALSE) {
freopen("/dev/null", "w", stderr);
if (setjmp(jbuf) != 0) {
source->initp = FALSE;
}
else {
signal(SIGALRM, alarmhandler);
old = alarm(new);
init_for_source(source, q->request_message, MAX_MESSAGE_LEN,
q->response_message);
alarm(old);
signal(SIGALRM, SIG_DFL);
}
request_buffer_length = source->buffer_length;
if(source->initp == FALSE) {
printf("not responding.\n");
}
else { /* now lets test the database */
if(source->database[0] == 0) database = NULL;
else database = source->database;
if(NULL ==
generate_search_apdu(request_message + HEADER_LENGTH,
&request_buffer_length,
"?", database, NULL, 1)) {
PrintStatus("Buffer overflow: request too large");
}
else {
long r = 0;
if (setjmp(jbuf) != 0) {
printf("not responding:\n");
return;
} else {
signal(SIGALRM, alarmhandler);
old = alarm(new);
if(0 ==
(r = interpret_message(request_message,
(source->buffer_length -
request_buffer_length),
response_message,
source->buffer_length,
source->connection,
false /* true verbose */
))) {
PrintStatus("Warning: no information returned. Possibly a bad connection");
}
}
if(r != 0) {
readSearchResponseAPDU(&q->query_response,
response_message + HEADER_LENGTH);
if (q->query_response != NULL)
if ((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords != NULL)
if ((diag =
((WAISSearchResponse *)q->query_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL) {
printf("not responding:\n");
printDiags(diag);
}
else
printf("responding.\n");
}
}
}
}
}
}
}
else {
printf("\nError: No sources to search. Please add one.\n");
}
}
void close_source(source)
Source source;
{
SList t;
if (source->connection != NULL) {
fclose(source->connection);
}
for(t = Sources; t != NULL; t = t->nextSource) {
if (strcmp(t->thisSource->server, source->server) == 0 &&
strcmp(t->thisSource->service, source->service) == 0) {
t->thisSource->initp = FALSE;
t->thisSource->connection = NULL;
}
}
}
DocumentID
getNextorPrevDoc(q, source, doc, nextp)
Question q;
Source source;
DocumentID doc;
Boolean nextp;
{
static long request_length;
static long lines, size, count, numChars;
any* docany;
char message[255];
int i;
diagnosticRecord **diag;
char *database, *type;
DocumentID result;
DocID *newdoc;
DocObj *Doc[2];
WAISSearchResponse *info;
char *text, document_id[MAX_FILE_NAME_LEN];
char *loc1, *loc2, *loc3, newtype[100], headline[MAX_FILE_NAME_LEN];
long newsize;
if(source->database[0] == 0) database = NULL;
else database = source->database;
docany = anyFromDocID(doc->doc->id);
size = 0;
if(nextp == TRUE)
type = "WAIS_NEXT";
else
type = "WAIS_PREV";
if(source->initp == FALSE)
init_for_source(source,q->request_message,MAX_MESSAGE_LEN,
q->response_message);
request_length = source->buffer_length;
Doc[0] = makeDocObjUsingWholeDocument(docany, s_strdup(type));
Doc[1] = NULL;
if(0 ==
generate_search_apdu(q->request_message + HEADER_LENGTH,
&request_length,
"foo", database, Doc, 1)) {
PrintStatus("\nWarning: Buffer overflow.");
return NULL;
}
if(0 ==
interpret_message(q->request_message,
(source->buffer_length - request_length),
q->response_message,
source->buffer_length,
source->connection,
false /* true verbose */
)) {
PrintStatus("\nWarning: no information returned. Possibly a bad connection. Maybe try again.");
source->initp = FALSE;
return NULL;
}
readSearchResponseAPDU(&q->retrieval_response,
q->response_message + HEADER_LENGTH);
if (q->retrieval_response != NULL)
if ((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords != NULL)
if ((diag =
((WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords)->Diagnostics) != NULL)
showDiags(diag);
info = (WAISSearchResponse *)q->retrieval_response->DatabaseDiagnosticRecords;
if (info != NULL &&
info->DocHeaders != NULL) {
return(fillDocumentID(info->DocHeaders[0], doc->doc->sourceID));
}
else return NULL;
}